/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dk.rofl.modes;

import dk.eleit.input.InputManager;
import dk.rofl.items.*;
import dk.rofl.maps.GameMap;
import dk.rofl.units.DamageReport;
import dk.rofl.units.Monster;
import dk.rofl.units.Player;
import dk.rofl.units.UnitUtils;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import rofl.RoFL;

/**
 *
 * @author menderleit
 */
public class CombatMode extends Mode {

    public static final int MENU_ATTACK = 0;
    public static final int MENU_PARRY = 1;
    public static final int MENU_USE = 2;
    public static final int MENU_RETREAT = 3;
    public static final int DMG_NONE = 0;
    public static final int DMG_PLAYER = 1;
    public static final int DMG_ENEMY = 2;
    public static final int TURN_NONE = 0;
    public static final int TURN_PLAYER = 1;
    public static final int TURN_ENEMY = 2;
    private static final long turnDelay = 1500;
    private GameMap map;
    private Player player;
    private Monster enemy;
    private int turn;
    private long turnTime;
    private int whoDidDmg;
    private DamageReport dmgReport;
    private DamageReport riposteReport;
    private GameChest gc;
    private int menuSelected;
    private boolean itemMenu;
    private boolean turnTaken;
    private ArrayList<GameItem> items;

    // Constructor
    public CombatMode(GameMap map, Player player, Monster enemy, int startTurn) {
        this.map = map;
        this.player = player;
        this.enemy = enemy;
        turn = startTurn;
        turnTime = turnDelay;
        whoDidDmg = DMG_NONE;
        menuSelected = 0;
        itemMenu = false;
        turnTaken = false;
        items = player.getCombatItems();
    }

    @Override
    public void controls(InputManager im) {
        if (turn == TURN_PLAYER) {
            if (im.isKeyDown(KeyEvent.VK_DOWN) && !GameModeUtils.getKeyLock()) {
                GameModeUtils.setKeyLock(true);
                if (!itemMenu) {
                    if (menuSelected < 3) {
                        menuSelected++;
                    } else {
                        menuSelected = 0;
                    }
                } else {
                    if (menuSelected <= items.size()) {
                        if(menuSelected < items.size()) {
                            menuSelected++;
                        } else {
                            menuSelected = 0;
                        }
                    } else {
                        menuSelected = 0;
                    }
                }
            }
            if (im.isKeyDown(KeyEvent.VK_UP) && !GameModeUtils.getKeyLock()) {
                GameModeUtils.setKeyLock(true);
                if (menuSelected > 0) {
                    menuSelected--;
                } else {
                    if (!itemMenu) {
                        menuSelected = 3;
                    } else {
                        menuSelected = items.size();
                    }
                }
            }
            if (im.isKeyDown(KeyEvent.VK_ENTER) && !GameModeUtils.getKeyLock()) {
                GameModeUtils.setKeyLock(true);
                if (!turnTaken) {
                    if (!itemMenu) {
                        switch (menuSelected) {
                            case MENU_ATTACK:
                                turnTaken = true;
                                dmgReport = player.attack(enemy);
                                whoDidDmg = DMG_PLAYER;
                                turnTime = turnDelay;
                                break;
                            case MENU_PARRY:
                                turnTaken = true;
                                whoDidDmg = DMG_NONE;
                                player.tryToParry();
                                turnTime = turnDelay / 2;
                                break;
                            case MENU_USE:
                                itemMenu = true;
                                menuSelected = 0;
                                break;
                        }
                    } else {
                        if (menuSelected < items.size()) {
                            GameItem gi = items.get(menuSelected);
                            switch (gi.getItemType()) {
                                case GameItem.TYPE_POTION:
                                    HealthPotion hp = (HealthPotion) gi;
                                    dmgReport = new DamageReport(0, 0, -hp.getHealth(), false, false, false);
                                    whoDidDmg = DMG_ENEMY;
                                    player.addHealth(-dmgReport.getDamageDone());
                                    if(hp.getNumPotions() == 0) {
                                        items.remove(menuSelected);
                                    }
                                    player.removeUsedCombatItem(hp);
                                    break;
                            }
                        } else {
                            itemMenu = false;
                            menuSelected = MENU_USE;
                        }
                    }
                }
            }
        }
    }

    @Override
    public void update(long difTime) {
        if (player.isDead()) {
            GameModeUtils.setGameMode(GameModeUtils.STATE_DEAD);
            turn = TURN_NONE;
            turnTime = 0;
        }
        if (enemy.isDead()) {
            gc = enemy.getChestReward();
            player.addXp(enemy.getExperience());
            player.getChestReward(gc);
            GameModeUtils.setGameMode(GameModeUtils.STATE_DEAD);
            turn = TURN_NONE;
            turnTime = 0;
        }
        switch (turn) {
            case TURN_PLAYER:
                if (turnTaken) {
                    turnTime -= difTime;
                    if (turnTime <= 0) {
                        turnTaken = false;
                        turn = TURN_ENEMY;
                    }
                }
                break;
            case TURN_ENEMY:
                if (!turnTaken) {
                    turnTaken = true;
                    dmgReport = enemy.attack(player);
                    if (dmgReport.getRiposte()) {
                        riposteReport = player.attack(enemy);
                    }
                    whoDidDmg = DMG_ENEMY;
                    turnTime = 0;
                } else {
                    turnTime -= difTime;
                    if (turnTime <= 0) {
                        turnTaken = false;
                        turn = TURN_PLAYER;
                    }
                }
                break;
        }
    }

    @Override
    public void draw(Graphics2D g) {
        FontMetrics fm = g.getFontMetrics();

        int yPos = 300;

        g.drawImage(player.getImage(), null, 275, yPos);
        g.drawImage(enemy.getImage(), null, 725, yPos);

        String s;

        if (GameModeUtils.getGameMode() != GameModeUtils.STATE_DEAD) {
            s = "- VS -";
            int x = RoFL.SCREEN_WIDTH / 2 - fm.stringWidth(s) / 2;
            int y = RoFL.SCREEN_HEIGHT / 2 - fm.getHeight() / 2;
            g.setColor(Color.yellow);
            g.drawString(s, x, y);
        }

        int ty = fm.getHeight();
        s = "Player";
        g.drawString(s, 275 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Health: " + player.getCurrentHealth() + "/" + player.getMaxHealth();
        g.drawString(s, 275 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Stamina: " + player.getStamina();
        g.drawString(s, 275 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Strength: " + player.getStrength();
        g.drawString(s, 275 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Armor: " + player.getArmorRating();
        g.drawString(s, 275 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Weapon: " + player.getWeapon().getName() + "(" + player.getWeapon().getMinDamage() + "-" + player.getWeapon().getMaxDamage() + ")";
        g.drawString(s, 275 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);

        ty = fm.getHeight();
        s = "Level " + enemy.getLevel() + " " + enemy.getName();
        g.drawString(s, 725 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Health: " + enemy.getCurrentHealth() + "/" + enemy.getMaxHealth();
        g.drawString(s, 725 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Stamina: " + enemy.getStamina();
        g.drawString(s, 725 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Strength: " + enemy.getStrength();
        g.drawString(s, 725 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Armor: " + enemy.getArmorRating();
        g.drawString(s, 725 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);
        ty += fm.getHeight();
        s = "Weapon: " + enemy.getWeapon().getName() + "(" + enemy.getWeapon().getMinDamage() + "-" + enemy.getWeapon().getMaxDamage() + ")";
        g.drawString(s, 725 + 16 - fm.stringWidth(s) / 2, yPos + 32 + ty);

        // Draw the damage done.
        if (whoDidDmg != DMG_NONE) {
            g.setColor(Color.lightGray);
            if (dmgReport.getDamageDone() > 0) {
                g.setColor(Color.red);
            } else if (dmgReport.getDamageDone() < 0) {
                g.setColor(Color.green);
            }
            s = "" + Math.abs(dmgReport.getDamageDone());
            if (dmgReport.wasCriticalStrike() && !dmgReport.wasParried()) {
                s += " (critital)";
            }
            if (dmgReport.wasParried()) {
                s += " (parried)";
                g.setColor(Color.cyan);
            }
            if (whoDidDmg == DMG_PLAYER) {
                g.drawString(s, 725 + 16 - (fm.stringWidth(s) / 2), yPos - 24);
            }
            if (whoDidDmg == DMG_ENEMY) {
                g.drawString(s, 275 + 16 - (fm.stringWidth(s) / 2), yPos - 24);
                if (dmgReport.getRiposte()) {
                    s = "" + riposteReport.getDamageDone() + " (riposte)";
                    g.setColor(Color.red);
                    g.drawString(s, 725 + 16 - (fm.stringWidth(s) / 2), yPos - 24);
                }
            }
        }
        if (GameModeUtils.getGameMode() == GameModeUtils.STATE_DEAD) {
            if (player.isDead()) {
                g.setColor(Color.red);
                s = "You died! (GAME OVER)";
            } else {
                g.setColor(Color.green);
                s = "You defeated the " + enemy.getName() + "!";
            }
            int sW = fm.stringWidth(s) / 2;
            int sH = fm.getHeight() / 2;
            g.drawString(s, RoFL.SCREEN_WIDTH / 2 - sW, RoFL.SCREEN_HEIGHT / 2 - sH);
            s = "Press SPACE to Continue";
            sW = fm.stringWidth(s) / 2;
            sH = fm.getHeight() / 2 - 2 * fm.getHeight();
            g.setColor(Color.yellow);
            g.drawString(s, RoFL.SCREEN_WIDTH / 2 - sW, RoFL.SCREEN_HEIGHT / 2 - sH);
            if (!player.isDead()) {
                s = "- LOOT -";
                sW = fm.stringWidth(s) / 2;
                sH = fm.getHeight() / 2 - 5 * fm.getHeight();
                g.setColor(Color.white);
                g.drawString(s, RoFL.SCREEN_WIDTH / 2 - sW, RoFL.SCREEN_HEIGHT / 2 - sH);
                ArrayList<GameItem> loot = gc.getItems();
                for (int i = 0; i < loot.size(); i++) {
                    GameItem gi = loot.get(i);
                    s = "[" + gi.getItemLevel() + "] " + gi.getName();
                    sW = fm.stringWidth(s) / 2;
                    sH = fm.getHeight() / 2 - (7 + i) * fm.getHeight();
                    if (gi instanceof Armor || gi instanceof Weapon) {
                        Equipment e = (Equipment) gi;
                        g.setColor(Equipment.getItemQualityColor(e.getItemQuality()));
                    } else {
                        g.setColor(Color.lightGray);
                    }
                    g.drawString(s, RoFL.SCREEN_WIDTH / 2 - sW, RoFL.SCREEN_HEIGHT / 2 - sH);
                }
            }
        }

        // Player Menu
        if (turn == TURN_PLAYER && !turnTaken) {
            int xPos = RoFL.SCREEN_WIDTH / 2;
            yPos += 200;
            s = "- ACTIONS -";
            int sW = fm.stringWidth(s) / 2;
            int sH = fm.getHeight();
            g.setColor(Color.white);
            g.drawString(s, xPos - sW, yPos - sH * 2);
            if (!itemMenu) {
                String[] mItem = {" Attack ", " Parry ", " Use Item ", " Retreat "};
                for (int i = 0; i <= MENU_RETREAT; i++) {
                    s = mItem[i];
                    sW = fm.stringWidth(s) / 2;
                    sH = fm.getHeight();
                    if (i == menuSelected) {
                        g.setColor(Color.darkGray);
                        g.fillRect(xPos - sW, yPos + i * sH - sH + 4, fm.stringWidth(s), fm.getHeight());
                    }
                    g.setColor(Color.white);
                    g.drawString(s, xPos - sW, yPos + i * sH);
                }
            } else {
                for (int i = 0; i <= items.size(); i++) {
                    if (i < items.size()) {
                        GameItem gi = items.get(i);
                        s = "[" + gi.getItemLevel() + "] " + gi.getName();
                        if(gi instanceof HealthPotion) {
                            HealthPotion hp = (HealthPotion) gi;
                            s += " " + hp.getHealingString();
                        }
                        sW = fm.stringWidth(s) / 2;
                        sH = fm.getHeight();
                        if (i == menuSelected) {
                            g.setColor(Color.darkGray);
                            g.fillRect(xPos - sW, yPos + i * sH - sH + 4, fm.stringWidth(s), fm.getHeight());
                        }
                        g.setColor(Color.lightGray);
                        g.drawString(s, xPos - sW, yPos + i * sH);
                    } else {
                        s = "[ BACK ]";
                        sW = fm.stringWidth(s) / 2;
                        sH = fm.getHeight();
                        if (i == menuSelected) {
                            g.setColor(Color.darkGray);
                            g.fillRect(xPos - sW, yPos + i * sH - sH + 4, fm.stringWidth(s), fm.getHeight());
                        }
                        g.setColor(Color.lightGray);
                        g.drawString(s, xPos - sW, yPos + i * sH);
                    }
                }
            }
        }
    }

    @Override
    public void exit() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
